package com.riq;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.riq.entity.Alert;
import com.riq.entity.Department;
import com.riq.entity.Icon;
import com.riq.entity.Location;
import com.riq.entity.Member;
import com.riq.entity.Status;
import com.riq.entity.Tracking;


@SuppressWarnings("serial")
public class AdminDepartmentServlet extends HttpServlet {
  private static final Logger log = Logger.getLogger(Department.class.getName());

  @Override
  public void doPost(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
    doGet(request, response);
  }

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException { 

  // ---------------------------------------------------------------------------------------------
  //  HEADER
  // ---------------------------------------------------------------------------------------------

    Cookie[] cookie = request.getCookies();
    Long deptId = Long.valueOf("999777");
    Long memberId = Long.valueOf("999222");
    
    if (cookie != null) {
    deptId = Long.valueOf(ServletUtilities.getCookieValue(cookie, "cvDeptId", "99999"));
    memberId = Long.valueOf(ServletUtilities.getCookieValue(cookie, "cvMemberId", "99999"));
    }
    String intent = request.getParameter("intent"); 
    String action = request.getParameter("action"); 
    

  // ---------------------------------------------------------------------------------------------
  //  METHOD DIRECTORY
  // ---------------------------------------------------------------------------------------------

  // DEPARTMENT

    if ("create".equalsIgnoreCase(action)) { 
      create(response, request); 
    } else if ("display".equalsIgnoreCase(action)) { 
      display(response, request, deptId, memberId); 
    } else if ("edit".equalsIgnoreCase(action)) { 
      edit(response, request, deptId); 
    } else if ("set".equalsIgnoreCase(action)) { 
      set(response, request, deptId); 
    } else if ("lookup".equalsIgnoreCase(action)) { 
      lookup(response, request); 
    } else if ("polling".equalsIgnoreCase(action)) { 
      polling(response, request, deptId, intent); 

  // ALERTS

    } else if ("alertCreate".equalsIgnoreCase(action)) { 
      alertCreate(response, request); 
    } else if ("alertTerminate".equalsIgnoreCase(action)) { 
      alertTerminate(response, request); 
    } else if ("alertAutoTerminate".equalsIgnoreCase(action)) { 
        alertTerminate(response, request); 
    } else if ("alertHistory".equalsIgnoreCase(action)) { 
      alertHistory(response, request, deptId); 
      
  // TRACKS (TODO: remove at launch) 
      
    } else if ("purgeTracks".equalsIgnoreCase(action)) { 
        purgeTracks(response, request, deptId); 

      
    } else { response.sendRedirect("mainMenu.html"); }
  }

  
  // -----------------------------------------------------------------------------------------------
  // DEPARTMENT ADMINISTRATION
  // -----------------------------------------------------------------------------------------------

  
  private void create(HttpServletResponse response, ServletRequest request) {

    PersistenceManager pm = PMF.get().getPersistenceManager();

    double coordLat = new Double("5.0").doubleValue();
    double coordLng = new Double("5.0").doubleValue();
    
    String coordinatesLatitude = request.getParameter("markerLat");
    if (coordinatesLatitude != null) {
    coordLat = new Double(coordinatesLatitude).doubleValue();
    }

    String coordinatesLongitude = request.getParameter("markerLng");
    if (coordinatesLongitude != null) {
    coordLng = new Double(coordinatesLongitude).doubleValue();
    }
  
    long distGroupA = 5;
    distGroupA = Long.valueOf(request.getParameter("distGroupA"));
    long distGroupB = 10;
    distGroupB = Long.valueOf(request.getParameter("distGroupB"));
    long distGroupC = 25;
    distGroupC = Long.valueOf(request.getParameter("distGroupC"));
    long distMaxAge = 360;
    distMaxAge = Long.valueOf(request.getParameter("distMaxAge"));
    
    String timeStamp = String.valueOf(System.currentTimeMillis());

    Department d = new Department(
        timeStamp + "|" + request.getParameter("shortName"),
        request.getParameter("longName"),
        request.getParameter("type"),
        request.getParameter("fromEmail"),
        request.getParameter("trackingFlag"),
        coordLat,
        coordLng,
        distGroupA,
        distGroupB,
        distGroupC,
        distMaxAge,
        request.getParameter("dispatchId"),
        request.getParameter("username"),
        request.getParameter("password"),
        request.getParameter("mutualAid"),
        request.getParameter("inboundVRU1"),
        request.getParameter("inboundVRU2"),
        request.getParameter("inboundVRU3")
      );
      pm.makePersistent(d);
    
      
    String queryLocation = "select from " + Department.class.getName() + 
    " where shortName == '" +  timeStamp + "|" + request.getParameter("shortName") + "' ";
    List<Department> d1 = (List<Department>) pm.newQuery(queryLocation).execute();
    String deptId = d1.get(0).getid().toString();
    
    if (d1 != null) {
    d1.get(0).setshortName(request.getParameter("shortName"));
    pm.makePersistent(d1);
    }
  
    pm.close();
    try
    {
      response.sendRedirect("c?action=deptCookie&deptId=" + deptId);
    } catch (IOException e)
    {
      // TODO
      e.printStackTrace();
    }
  }
    
     

  // DEPT EDIT

  private void edit(HttpServletResponse response, ServletRequest request, 
          Long deptId) {

    PersistenceManager pm = PMF.get().getPersistenceManager();

    deptId = Long.valueOf(request.getParameter("deptId"));
    Department d = pm.getObjectById(Department.class, deptId);
    request.setAttribute("dept", d);
    
    String queryLocation = "select from " + Location.class.getName() + 
    " where deptId == " + deptId;
    List<Location> locations = (List<Location>) pm.newQuery(queryLocation).execute();
    request.setAttribute("locations", locations);
    
    RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/deptEdit.jsp");
    try
    {
      dispatcher.forward(request, response);
    } catch (ServletException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }  
  }

  // DEPT SET
  
  private void set(HttpServletResponse response, ServletRequest request, Long deptId) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    Long deptId2 =  Long.valueOf(request.getParameter("deptId"));
    Department d = pm.getObjectById(Department.class, deptId2); 

    log.info("DeptId being edited: " + d.getid());
    
    String coordinatesLatitude = request.getParameter("markerLat");
    double coordLat = new Double(coordinatesLatitude).doubleValue();
    d.setcoordinatesLatitude(coordLat);

    String coordinatesLongitude = request.getParameter("markerLng");
    double coordLng = new Double(coordinatesLongitude).doubleValue();
    d.setcoordinatesLongitude(coordLng);

    String distGroupA = request.getParameter("distGroupA");
    int dgA = new Integer(distGroupA).intValue();
    d.setdistGroupA(dgA);

    String distGroupB = request.getParameter("distGroupB");
    int dgB = new Integer(distGroupB).intValue();
    d.setdistGroupB(dgB);

    String distGroupC = request.getParameter("distGroupC");
    int dgC = new Integer(distGroupC).intValue();
    d.setdistGroupC(dgC);

    String distMaxAge = request.getParameter("distMaxAge");
    int maxAge = new Integer(distMaxAge).intValue();
    d.setdistMaxAge(maxAge);

    d.setshortName(request.getParameter("shortName"));
    d.setlongName(request.getParameter("longName"));
    d.settype(request.getParameter("type"));
    d.setfromEmail(request.getParameter("fromEmail"));
    d.settrackingFlag(request.getParameter("trackingFlag"));
    d.setdispatchId(request.getParameter("dispatchId"));
    d.setusername(request.getParameter("username"));
    d.setpassword(request.getParameter("password"));
    d.setmutualAid(request.getParameter("mutualAid"));
//    d.setinboundVRU1(request.getParameter("inboundVRU1"));
//    d.setinboundVRU2(request.getParameter("inboundVRU2"));
//    d.setinboundVRU3(request.getParameter("inboundVRU3"));

    pm.makePersistent(d); 
    pm.close();
    try
    {
      response.sendRedirect("department?action=display");
    } catch (IOException e)
    {
      // TODO
      e.printStackTrace();
    }
  }
  
  // DEPT POLLING

  private void polling(HttpServletResponse response, ServletRequest request, 
          Long deptId, String intent) {

    log.info("Inside polling");

    List<Long> deptsIncluded = new ArrayList<Long>();
    PersistenceManager pm = PMF.get().getPersistenceManager();
    Department d = (Department) pm.getObjectById(Department.class, deptId);

    // if requested, add mutual aid depts to dept list 
    // user must separate deptIds with a comma during input
    // TODO: need to validate this input
    String maFlag = request.getParameter("mutualAid");
    if ("yes".equalsIgnoreCase(maFlag)) {
      String mutualAidDepts = d.getmutualAid();
      String[] maDepts = mutualAidDepts.split(", ", -1);
      for (int i=0; i< maDepts.length; i++) {
        Long maDeptId = Long.valueOf(maDepts[i]);
        deptsIncluded.add(maDeptId);
      }
    }

    deptsIncluded.add(deptId);  

    // create list of allDepts for report and set as attribute for polling.jsp
    Query queryD = pm.newQuery(Department.class, ":p.contains(id)");
    List<Department> allDepts = (List<Department>)queryD.execute(deptsIncluded);
    request.setAttribute("allDepts", allDepts);

    // get all members from allDepts
    Query queryM = pm.newQuery(Member.class, ":p.contains(deptId)");
    List<Member> members = (List<Member>)queryM.execute(deptsIncluded);

    // bucket members into distance range lists to get count for subheads in jsp
    // TODO johnreilly dept subtotals are not working in mutual aid "readiness" report
    List<Member> membersRangeX = new ArrayList<Member>();
    List<Member> membersRangeA = new ArrayList<Member>();
    List<Member> membersRangeB = new ArrayList<Member>();
    List<Member> membersRangeC = new ArrayList<Member>();
    List<Member> membersRangeD = new ArrayList<Member>();

    for (Member m : members) {
      if ("001".equalsIgnoreCase(m.getdistGroup())) {
        membersRangeA.add(m);
        continue;
      } else if ("002".equalsIgnoreCase(m.getdistGroup())) {
        membersRangeB.add(m);
        continue;
      } else if ("003".equalsIgnoreCase(m.getdistGroup())) {
        membersRangeC.add(m);
        continue;
      } else if ("004".equalsIgnoreCase(m.getdistGroup())) {
        membersRangeD.add(m);
        continue;
      } else {
        membersRangeX.add(m);
      }
    }

    // DEBUG
//    log.info("RangeA Qty: " + membersRangeA.size());
//    log.info("RangeB Qty: " + membersRangeB.size());
//    log.info("RangeC Qty: " + membersRangeC.size());
//    log.info("RangeD Qty: " + membersRangeD.size());
//    log.info("RangeX Qty: " + membersRangeX.size());

    request.setAttribute("membersRangeA", membersRangeA);
    request.setAttribute("membersRangeB", membersRangeB);
    request.setAttribute("membersRangeC", membersRangeC);
    request.setAttribute("membersRangeD", membersRangeD);
    request.setAttribute("membersRangeX", membersRangeX);

    // created to send periodic email report with quantities of Members in each distGroup
    if ("email".equalsIgnoreCase(intent)) {

      String newline = System.getProperty("line.separator");
      Properties props = new Properties();
      Session session = Session.getDefaultInstance(props, null);
      String msgBody = "0-" + d.getdistGroupA() + 
      " Minutes: " + membersRangeA.size() +
      newline + d.getdistGroupA()+ "-" + d.getdistGroupB() + 
      " Minutes: " + membersRangeB.size() +
      newline + d.getdistGroupB()+ "-" + d.getdistGroupC() + 
      " Minutes: " + membersRangeC.size() +
      newline +  " Over " + d.getdistGroupC() + 
      " Minutes: " + membersRangeD.size() +
      newline +  " Unknown: " + membersRangeX.size();

      try {
        Message msg = new MimeMessage(session);
        msg.setFrom(new InternetAddress("jreilly@gmail.com", "FirstResponder Admin"));
        msg.addRecipient(Message.RecipientType.TO,  
                new InternetAddress("9732559900@sprintpcs.messaging.com", "Responder"));
//                new InternetAddress(d.getfromEmail(), "Responder"));

        msg.setSubject("FirstResponder Readiness Report: " + d.getshortName());
        msg.setText(msgBody);
        Transport.send(msg);
      } catch (MessagingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      } catch (UnsupportedEncodingException e)
      {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }

    log.info("Leaving deptServ.polling");
    RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/deptPolling.jsp");
    try
    {
      dispatcher.forward(request, response);
    } catch (ServletException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }  
  }

  private void lookup(HttpServletResponse response, ServletRequest request) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    String query = "select from " + Department.class.getName() + 
    " where shortName == '" + request.getParameter("searchName")+"'";
    List<Department> departments = (List<Department>) pm.newQuery(query).execute();
    request.setAttribute("departments", departments);
    RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/deptLookup.jsp");
    try
    {
      dispatcher.forward(request, response);
    } catch (ServletException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
  
  // -----------------------------------------------------------------------------------------------
  // ALERT ADMINISTRATION
  // -----------------------------------------------------------------------------------------------

  private void alertCreate(HttpServletResponse response, ServletRequest request) {

    Long timeStamp = System.currentTimeMillis();
    Alert a = new Alert (
            Long.valueOf(request.getParameter("deptId")),
            timeStamp,
            request.getParameter("alertMsgString"),
            request.getParameter("fromEmailAddress"),
            request.getParameter("status"),
            request.getParameter("rawMessage"),
            request.getParameter("lat"),
            request.getParameter("lng"),
            request.getParameter("messageId")
    );
    PersistenceManager pm = PMF.get().getPersistenceManager();
    pm.makePersistent(a); 
    try
    {
      response.sendRedirect("department?action=deptDisplay&deptId=" + a.getdeptId());
    } catch (IOException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }	 
  }


  private void alertTerminate(HttpServletResponse response, ServletRequest request) {
    Long alertId = Long.valueOf(request.getParameter("alertId"));
    PersistenceManager pm = PMF.get().getPersistenceManager();
    Alert a = pm.getObjectById(Alert.class, alertId);
    log.info("alert message: " + a.getalertMsgString());

    // need single attribute update for cache
    a.setstatus("Terminated|Manual");
    pm.makePersistent(a); 
    pm.close();
    try
    {
      response.sendRedirect("markup?action=alertSelect&intent=terminate");
    } catch (IOException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
  

  private void alertAutoTerminate(HttpServletResponse response, ServletRequest request) {
	  
	PersistenceManager pm = PMF.get().getPersistenceManager();
	String queryAlertIds = "select id from " + Alert.class.getName() + 
	" where status == 'active' ";
	List<Alert> activeAlertIds = (List<Alert>) pm.newQuery(queryAlertIds).execute();
	
	String queryAlerts = "select from " + Alert.class.getName() + 
	" where status == 'active' ";
	List<Alert> activeAlerts = (List<Alert>) pm.newQuery(queryAlerts).execute();
	
	Query queryTracks = pm.newQuery(Tracking.class, ":p.contains(alertId) && " +
			" ( type == 'member' || type == 'memberVoice' ) ");
	queryTracks.setOrdering("alertId asc, type asc");
	List<Tracking> activeTracks = (List<Tracking>)queryTracks.execute(activeAlertIds);

    // terminate Alerts that have no responders after one hour...
	TRACKS: for (Alert a : activeAlerts) {
		for (Tracking at : activeTracks) {
			if (a.getid().equals(at.getalertId()) && 
				a.gettimeStamp() < (System.currentTimeMillis() - 60*60*1000)) {
			    a.setstatus("Terminated|Auto");
			    pm.makePersistent(a); 
			    continue TRACKS;
			}
		}
	}
	
  pm.close();
  }
  

  private void alertHistory(HttpServletResponse response, ServletRequest request,
          Long deptId) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    String queryAlert = "select from " + Alert.class.getName() + 
    " where deptId == " + deptId;
    List<Alert> alerts = (List<Alert>) pm.newQuery(queryAlert).execute();

    if (alerts.isEmpty()) {
      try
      {
        response.sendRedirect("noSuchObject.jsp?errorMessage=noAlerts");
      } catch (IOException e)
      {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }

    request.setAttribute("alerts", alerts);
    RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/alertLogSelect.jsp");
    try
    {
      dispatcher.forward(request, response);
    } catch (ServletException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }  
  }


  // -----------------------------------------------------------------------------------------------
  // DEPARTMENT UTILITIES
  // -----------------------------------------------------------------------------------------------

  // TODO: remove at launch
  private void purgeTracks(HttpServletResponse response, ServletRequest request, Long deptId) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    String query = "select from " + Tracking.class.getName() + " where deptId == " + deptId;
    List<Tracking> tracks = (List<Tracking>) pm.newQuery(query).execute();

    if (tracks.isEmpty()) {
      try
      {
        response.sendRedirect("noSuchObject.jsp?errorMessage=noTracks");
      } catch (IOException e)
      {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }

    pm.deletePersistentAll(tracks);
    pm.close();
    
    try {
		response.sendRedirect("noSuchObject.jsp?errorMessage=noAlerts");
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
   
  }

  
  private void display(HttpServletResponse response, ServletRequest request,
          Long deptId, Long memberId) {

    PersistenceManager pm = PMF.get().getPersistenceManager();
    log.info("deptId deptServ2: " + deptId.toString());

    // department
    Department d = (Department) pm.getObjectById(Department.class, deptId);
    request.setAttribute("d", d);
    log.info("deptName: " + d.getshortName());

    // members
    String queryMembers = "select from " + Member.class.getName() + 
    " where deptId == " + deptId + " order by type asc, lastName asc";
    List<Member> members = (List<Member>) pm.newQuery(queryMembers).execute();  
    request.setAttribute("members", members);
    log.info("members qty: " + members.size());

    // locations
    String queryLocations = "select from " + Location.class.getName() + 
    " where deptId == " + deptId + " order by sequence asc, shortName asc";
    List<Location> locations = (List<Location>) pm.newQuery(queryLocations).execute();
    request.setAttribute("locations", locations);
    log.info("locations qty: " + locations.size());

    // statuses
    String queryStatus = "select from " + Status.class.getName() + 
    " where deptId == " + deptId + " order by type asc, shortName asc ";
    List<Status> statuses = (List<Status>) pm.newQuery(queryStatus).execute();
    request.setAttribute("statuses", statuses);
    log.info("Statuses: " + statuses.size());
    
    // icons
    String queryIcons = "select from " + Icon.class.getName() + 
    " where deptId == " + deptId + " order by type asc, shortName asc ";
    List<Icon> icons = (List<Icon>) pm.newQuery(queryIcons).execute();
    request.setAttribute("icons", icons);
    log.info("Icons: " + icons.size());


    RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/deptDisplay.jsp");
    try
    {
      dispatcher.forward(request, response);
    } catch (ServletException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e)
    {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }  
  }
}

